
package com.hlkj.pay.app.merchant.ext.impl.heepay.ext;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.util.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderQueryContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelRefundPayOrderContext;
import com.hlkj.pay.app.merchant.ext.impl.heepay.constanct.HeePayConstant;
import com.hlkj.pay.app.merchant.ext.impl.heepay.dto.*;
import com.hlkj.pay.app.merchant.ext.impl.heepay.handler.HeePayMerchantCommonParamsHandle;
import com.hlkj.pay.app.merchant.ext.impl.heepay.util.HeePayParamUtils;
import com.hlkj.pay.app.merchant.ext.impl.helipay.constant.HeliPayConstant;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.order.RefundOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.util.DateUtils;
import com.hlkj.pay.util.MerchantUtils;
import com.hlkj.pay.util.ParamUtils;
import com.hlkj.pay.vo.order.req.OrderAccount;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 汇付宝 正扫 反扫 通用处理
 * 
 * @author HlpayTeam
 * @date 2024/10/11 16:22
 */
@Slf4j
@Repository
@RequiredArgsConstructor
public class HeePaySceneCommonPayOrder {

    @Autowired
    private HeePayMerchantCommonParamsHandle heePayMerchantCommonParamsHandle;

    /**
     * 汇付宝查询支付订单
     * 
     * @param channelPayOrderQueryContext
     */
    public void commonQueryChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        // 配置转换
        CommonResult<HeePayConfig> commonResult = heePayMerchantCommonParamsHandle.heePayConfig(channelPayOrderQueryContext.getProviderChannelConfigDO(),
                channelPayOrderQueryContext.isTest());
        HeePayConfig heliPayConfig = commonResult.getData();

        PayOrderDO payOrderDO = channelPayOrderQueryContext.getPayOrderDO();
        HeePayAppChannelParams heliPayAppChannelParams = heePayMerchantCommonParamsHandle.heePayAppChannelParams(channelPayOrderQueryContext.getMerchantAppChannelDO(),heliPayConfig);
        PayWayDO payWayDO = channelPayOrderQueryContext.getPayWayDO();
        try {
            Map<String, String> params = new HashMap<>();
            params.put("version", "2");
            params.put("agent_id", heliPayConfig.getAgentId());
            params.put("agent_bill_id", payOrderDO.getPayOrderNo());
            params.put("agent_bill_time", DateUtils.dateToString(payOrderDO.getCreateTime(), "yyyyMMddHHmmss"));
            params.put("return_mode", "1");
            CommonResult<String> resultResult = heePayMerchantCommonParamsHandle.heePayOrderRequest(HeePayConstant.PAY_ORDER_QUERY_URL, heliPayConfig, params,
                    HeePayConstant.PAY_ORDER_QUERY_FIELD);
            log.info("汇付宝 支付订单查询 返回参数:{}", JsonUtils.toJsonString(resultResult));
            if (!resultResult.isSuccess()) {
                channelPayOrderQueryContext.setRemark("汇付宝支付订单查询请求失败,失败信息:" + resultResult.getMsg());
                channelPayOrderQueryContext.setProcessStatus(Boolean.FALSE);
                return;
            }
            Map<String, String> paramsMap = HeePayParamUtils.params(resultResult.getData());
            HeePayOrderQueryRes heePayOrderQueryRes = JsonUtils.parseObject(JsonUtils.toJsonString(paramsMap), HeePayOrderQueryRes.class);
            PayOrderDO updartePayOrderDO = new PayOrderDO();
            channelPayOrderQueryContext.setUpdartePayOrderDO(updartePayOrderDO);
            // HeePayOrderQueryRes heePayOrderQueryRes = JsonUtils.parseObject(heliPayOrderQueryRes.getData(), HeePayOrderQueryRes.class);
            // 汇元单据状态，PROCESS=处理中 SUCCESS=成功 FAIL=失败
            switch (heePayOrderQueryRes.getResult()) {
                case "1":
                    updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.SUCCESS.getCode());
                    updartePayOrderDO.setBankMsg("");
                    break;
                case "-1":
                    updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.FAIL.getCode());
                    break;
                default:
                    updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.PAYING.getCode());
                    updartePayOrderDO.setBankMsg("");
                    break;

            }
            if (StringUtils.hasText(heePayOrderQueryRes.getDeal_time())) {
                try {
                    updartePayOrderDO.setSuccessTime(DateUtils.shanghaiDate(heePayOrderQueryRes.getDeal_time(), "yyyyMMddHHmmss"));
                }
                catch (Exception e) {
                    log.error("汇付宝 支付订单查询 返回 时间格式化错误 dateTime:{},message:{}", heePayOrderQueryRes.getDeal_time(), e.getMessage());
                }
            }
            updartePayOrderDO.setInsOrderNo(heePayOrderQueryRes.getThird_bill_no());
            updartePayOrderDO.setChannelOrderNo(heePayOrderQueryRes.getJnet_bill_no());
            if (StringUtils.hasText(heePayOrderQueryRes.getPay_amt())) {
                updartePayOrderDO.setPayAmount(MerchantUtils.stringToBigDecimal(heePayOrderQueryRes.getPay_amt()));
            }
            else {
                updartePayOrderDO.setPayAmount(payOrderDO.getAmount());
            }
            if (StringUtils.hasText(heePayOrderQueryRes.getPay_user())) {
                updartePayOrderDO.setUserId(heePayOrderQueryRes.getPay_user());
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("汇付宝 支付订单查询 请求失败 message:{}", e.getMessage(), e);
            channelPayOrderQueryContext.setRemark("汇付宝 支付订单查询 请求失败,失败信息:" + e.getMessage());
            channelPayOrderQueryContext.setProcessStatus(Boolean.FALSE);
            // channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.APPROVE_REFUSE);
        }
    }

    /**
     * 汇付宝关闭订单
     * 
     * @param channelPayOrderQueryContext
     */
    public void commonCloseChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
    }

    /**
     * 汇付宝查询关闭订单状态
     * 
     * @param channelPayOrderQueryContext
     */
    public void commonQueryChannelClosePayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        // 汇付宝无此接口
        PayOrderDO updartePayOrderDO = new PayOrderDO();
        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.CLOSE.getCode());
        channelPayOrderQueryContext.setUpdartePayOrderDO(updartePayOrderDO);
    }

    /**
     * 汇付宝订单退款
     * 
     * @param channelRefundPayOrderContext
     */
    public void commonRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        // 配置转换
        CommonResult<HeePayConfig> commonResult = heePayMerchantCommonParamsHandle.heePayConfig(channelRefundPayOrderContext.getProviderChannelConfigDO(),
                channelRefundPayOrderContext.isTest());
        HeePayConfig heliPayConfig = commonResult.getData();

        PayOrderDO payOrderDO = channelRefundPayOrderContext.getPayOrderDO();
        RefundOrderDO refundOrderDO = channelRefundPayOrderContext.getRefundOrderDO();
        HeePayAppChannelParams heliPayAppChannelParams = heePayMerchantCommonParamsHandle.heePayAppChannelParams(channelRefundPayOrderContext.getMerchantAppChannelDO(),heliPayConfig);
        try {
            Map<String, String> objectHashMap = new HashMap<>();
            objectHashMap.put("version", "1");
            objectHashMap.put("agent_id", heliPayConfig.getAgentId());
            // objectHashMap.put("agent_bill_id", payOrderDO.getPayOrderNo());
            objectHashMap.put("refund_details",
                    payOrderDO.getPayOrderNo() + "," + MerchantUtils.bigDecimalToString2(refundOrderDO.getRefundAmount()) + "," + refundOrderDO.getRefundOrderNo());
            objectHashMap.put("notify_url", channelRefundPayOrderContext.getNotifyUrl());
            objectHashMap.put("key", heliPayConfig.getMd5Key());
            log.info("汇付宝 订单退款 请求参数:{}", JsonUtils.toJsonString(objectHashMap));
            CommonResult<String> resultResult = heePayMerchantCommonParamsHandle.heePayRefundOrderRequest(HeePayConstant.REFUND_ORDER_SUBMIT_URL, heliPayConfig, objectHashMap,
                    HeePayConstant.REFUND_ORDER_SUBMIT_FIELD);
            log.info("汇付宝 订单退款 返回参数:{}", JsonUtils.toJsonString(resultResult));
            if (!resultResult.isSuccess()) {
                channelRefundPayOrderContext.setRemark("汇付宝订单关闭请求失败,失败信息:" + resultResult.getMsg());
                channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
                return;
            }
            String response = resultResult.getData();
            Map<String, Object> map = ParamUtils.xmlToObject(response, "GBK");
            HeePayCommonRes heliPayOrderCommonRes = JsonUtils.parseObject(JsonUtils.toJsonStringNotNull(map), HeePayCommonRes.class);

            if (HeePayConstant.REQUEST_SUCCESS.equals(heliPayOrderCommonRes.getRet_code())) {
                RefundOrderDO updateRefundOrderDO = new RefundOrderDO();
                updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.REFUNDING.getCode());
                channelRefundPayOrderContext.setUpdateRefundOrderDO(updateRefundOrderDO);
            }
            else {
                String respDesc = heliPayOrderCommonRes.getRet_msg();
                channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
                if (StringUtils.hasText(respDesc)) {
                    channelRefundPayOrderContext.setRemark(respDesc);
                }
                else {
                    channelRefundPayOrderContext.setRemark("汇付宝提交退款订单返回错误信息为空,错误码为:" + heliPayOrderCommonRes.getRet_code());
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("汇付宝提交退款订单请求失败 message:{}", e.getMessage(), e);
            channelRefundPayOrderContext.setRemark("汇付宝提交退款订单请求失败,失败信息:" + e.getMessage());
            channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }

    /**
     * 汇付宝订单退款状态查询
     * 
     * @param channelRefundPayOrderContext
     */
    public void commonQueryRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        // 配置转换
        CommonResult<HeePayConfig> commonResult = heePayMerchantCommonParamsHandle.heePayConfig(channelRefundPayOrderContext.getProviderChannelConfigDO(),
                channelRefundPayOrderContext.isTest());
        HeePayConfig heliPayConfig = commonResult.getData();

        PayOrderDO payOrderDO = channelRefundPayOrderContext.getPayOrderDO();
        RefundOrderDO refundOrderDO = channelRefundPayOrderContext.getRefundOrderDO();
        HeePayAppChannelParams heliPayAppChannelParams = heePayMerchantCommonParamsHandle.heePayAppChannelParams(channelRefundPayOrderContext.getMerchantAppChannelDO(),heliPayConfig);
        try {
            Map<String, String> params = new HashMap<>();
            params.put("version", "1");
            params.put("agent_id", heliPayConfig.getAgentId());
            params.put("agent_bill_id", payOrderDO.getPayOrderNo());
            params.put("agent_refund_bill_no", refundOrderDO.getRefundOrderNo());
            log.info("汇付宝 退款查询 请求参数:{}", JsonUtils.toJsonString(params));
            CommonResult<String> resultResult = heePayMerchantCommonParamsHandle.heePayRefundOrderRequest(HeePayConstant.REFUND_ORDER_QUERY_URL, heliPayConfig, params,
                    HeePayConstant.REFUND_ORDER_QUERY_FIELD);
            log.info("汇付宝 退款查询 返回参数:{}", JsonUtils.toJsonString(resultResult));
            if (!resultResult.isSuccess()) {
                channelRefundPayOrderContext.setRemark("汇付宝退款查询请求失败,失败信息:" + resultResult.getMsg());
                channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
                return;
            }
            String response = resultResult.getData();
            Map<String, Object> map = ParamUtils.xmlToObject(response, "GBK");
            HeePayRefundOrderQueryRes heliPayRefundOrderQueryRes = JsonUtils.parseObject(JsonUtils.toJsonString(map), HeePayRefundOrderQueryRes.class);
            RefundOrderDO updateRefundOrderDO = new RefundOrderDO();
            channelRefundPayOrderContext.setUpdateRefundOrderDO(updateRefundOrderDO);
            if (HeliPayConstant.REQUEST_SUCCESS.equals(heliPayRefundOrderQueryRes.getRet_code())) {
                String detailData = heliPayRefundOrderQueryRes.getDetail_data();
                // 汇付宝退款单号，商户退款单号，退款金额，退款状态，退款时间，记录内码；
                // 退款状态（success=成功，fail=失败，refunding=退款中）
                //-1=失败；0=处理中，1=退款中，2=退款成功
                String[] split = detailData.split(",");
                switch (split[3]) {
                    case "-1":
                        updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.FAIL.getCode());
                        updateRefundOrderDO.setBankMsg(split[5]);
                        break;
                    case "2":
                        updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.REFUND.getCode());
                        if (StringUtils.hasText(split[4])) {
                            try {
                                updateRefundOrderDO.setSuccessTime(DateUtils.shanghaiDate(split[4], "yyyy-MM-dd HH:mm:ss"));
                            }
                            catch (Exception e) {
                                log.error("汇付宝退款订单查询返回 时间格式化错误 dateTime:{},message:{}", split[4], e.getMessage());
                            }
                        }
                        break;
                    default:
                        updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.REFUNDING.getCode());
                }

            }
            else {
                String respDesc = heliPayRefundOrderQueryRes.getRet_msg();
                updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.FAIL.getCode());
                if (StringUtils.hasText(respDesc)) {
                    updateRefundOrderDO.setBankMsg(respDesc);
                }
                else {
                    channelRefundPayOrderContext.setRemark("汇付宝退款订单查询返回错误信息为空,错误码为:" + heliPayRefundOrderQueryRes.getRet_code());
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("汇付宝退款订单查询请求失败 message:{}", e.getMessage(), e);
            channelRefundPayOrderContext.setRemark("汇付宝提交支付订单请求失败,失败信息:" + e.getMessage());
            channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
            // channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.APPROVE_REFUSE);
        }
    }



    public String accountRuleJson(List<OrderAccount> accounts) {
        if (CollectionUtils.isEmpty(accounts)) {
            return JsonUtils.toJsonString(Collections.emptyList());
        }
        List<Map> maps = new ArrayList<>();
        accounts.stream().forEach(account -> {
            Map<String, Object> params = new HashMap<>();
            params.put("splitBillMerchantNo", account.getAccountNo());
            params.put("splitBillAmount", account.getAmount());
            maps.add(params);
        });
        return JsonUtils.toJsonString(maps);
    }

    public String expireMinute(Long time) {
        if (time == null) {
            return 30 + "";
        }
        return (time - System.currentTimeMillis()) / 1000 / 60 + "";
    }

}
